/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ssp.event;

import java.io.Serializable;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import ssp.ResourceManager;
import ssp.SimulationManager;

/**
 * イベントキューを表すクラス
 * @author yamazaki
 */
public class EventQueue implements ResourceManager {
    
    /**
     * イベントを発生時間順に並べるためのComparator
     */
    private static class EventComparator implements Comparator<Event> , Serializable {
        
        private static final long serialVersionUID = 5942591300997960045L;
        
        @Override
        public int compare(Event e1, Event e2) {
            return (int)(e1.getEventTime() - e2.getEventTime());
        }
        
    }
    
    /**
     * イベントを発生時間順に並べるためのComparatorインスタンス
     */
    private static final EventComparator EVENT_COMPARATOR = new EventComparator();
    
    /**
     * シミュレーション中で唯一のEventQueueインスタンス
     */
    private static EventQueue INSTANCE = new EventQueue();
    
    /**
     * イベントキュー
     */
    private Queue<Event> eventQueue;
    
    /**
     * 現在時刻（最後のイベントが実行された時間）
     */
    private double currentTime;
    
    /**
     * コンストラクタ<br>
     * シングルトンなのでprivateアクセス
     */
    private EventQueue() {
        init();
        SimulationManager.register(this);
    }

    /**
     * @return the INSTANCE
     */
    public static EventQueue getINSTANCE() {
        return INSTANCE;
    }
    
    @Override
    public final void init() {
        this.currentTime = 0.0;
        this.eventQueue = new PriorityQueue<Event>(11, EVENT_COMPARATOR);
    }
    
    /**
     * 指定のイベントをイベントキューに追加する
     * @param event イベント
     */
    public void addEvent(Event event) {
        this.eventQueue.add(event);
    }
    
    /**
     * 次のイベントを実行する
     */
    public void nextEvent() {
        Event next = eventQueue.poll();
        if(next == null) {
            throw new RuntimeException("no more event");
        }
        next.fire();
        currentTime = next.getEventTime();
    }
    
    /**
     * 現時時刻を返す
     * @return 現在時刻
     */
    public double getCurrentTime() {
        return this.currentTime;
    }
    
}
